Skip to content

feat(security): 权限审批闭环 + ask策略引擎完整实现#163

Merged
minorcell merged 5 commits into
1024XEngineer:mainfrom
Cai-Tang-www:main
Apr 6, 2026
Merged

feat(security): 权限审批闭环 + ask策略引擎完整实现#163
minorcell merged 5 commits into
1024XEngineer:mainfrom
Cai-Tang-www:main

Conversation

@Cai-Tang-www

@Cai-Tang-www Cai-Tang-www commented Apr 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • 完成权限审批闭环:permission_request -> TUI(y/a/n) -> runtime.ResolvePermission -> permission_resolved
  • 新增 runtime 显式审批通道与等待机制:ask 决策不再直接失败,而是阻塞等待用户决定。
  • 完成 session 级权限记忆并升级为“类别级命中”:支持 once / always(session) / reject(session),可对同类别工具复用授权。
  • 新增标准化策略引擎(PolicyEngine):支持优先级、多维匹配(action/resource/category/path/host)。
  • 落地策略:
    • bash 全量 ask
    • filesystem_write_* / filesystem_edit 全量 ask
    • filesystem_read_* 命中敏感路径 ask,私钥类命中 deny
    • webfetch 白名单(github.com / *.github.com / docs.*allow,其余 ask
  • bootstrap 默认接入推荐策略引擎,替换原全量 allow 静态网关。
  • 补齐 runtime / tools / tui / security 相关测试并通过。

Test

  • go test ./internal/security ./internal/app
  • go test ./internal/tools ./internal/runtime ./internal/tui
  • go test ./...

Closes #162
Refs #98

@codecov

codecov Bot commented Apr 5, 2026

Copy link
Copy Markdown

@Cai-Tang-www Cai-Tang-www changed the title feat(security/runtime): 实现 session 级 once / always / reject 权限记忆 feat(security): 权限审批闭环 + ask策略引擎完整实现 Apr 5, 2026
@phantom5099

Copy link
Copy Markdown
Collaborator

[P1] session 级权限记忆会覆盖后续的硬性 deny 规则。
internal/tools/manager.go#L191-L206 里,engine.Check() 之后又无条件用 sessionDecisions.resolve() 覆盖了最终 decision;而 internal/tools/session_memory.go#L125-L150 的 key 明确只按 action type + category,不区分具体 target。这样一来,只要用户先对一次敏感文件读取点了 always(session),后面同一 session 里再去读 ~/.ssh/id_rsa 这类本应命中 deny-sensitive-private-keys 的请求,也会被记忆直接放行。这个问题会把这次 PR 新加的 deny/ask 策略整体绕过去。

[P2] webfetch 白名单里的 docs.* 实际会放行任意 docs. 主机。
推荐策略把 internal/security/policy.go#L202 里的 docs.* 直接列进 allow whitelist,而匹配逻辑在 internal/security/policy.go#L455-L462 是对整个 hostname 做 glob。结果像 docs.attacker.com、docs.evil 这类域名也会被直接 allow,不会落到 ask-webfetch-non-whitelist。如果本意是“官方文档域名”,这个模式现在太宽了。

@Cai-Tang-www

Cai-Tang-www commented Apr 6, 2026

Copy link
Copy Markdown
Collaborator Author

修了 P1:session 记忆不再覆盖硬性 deny,仅在策略结果为 ask 时才走记忆。
internal/tools/manager.go:187
修了 P2:移除过宽的 docs.* 白名单,避免 docs.attacker.com 被误放行。
internal/security/policy.go:199

@Cai-Tang-www

Copy link
Copy Markdown
Collaborator Author

新增/增强回归测试,覆盖 deny 优先级、webfetch 主机匹配、session memory 细节。

@pionxe

pionxe commented Apr 6, 2026

Copy link
Copy Markdown
Collaborator

ResolvePermission 可被重复提交阻塞

ResolvePermissionpending.ResultCh <- decision 处是阻塞发送;当前 UI 在待审批状态下可连续触发 y/a/n,且 runResolvePermission 使用 context.Background()。第一次提交后若再次提交,可能在无消费者或通道已满时长期阻塞,造成后台 goroutine 泄漏与重复决策竞态。建议改为非阻塞提交(或增加“已提交”状态)并在 runtime 侧做幂等保护。

@pionxe

pionxe commented Apr 6, 2026

Copy link
Copy Markdown
Collaborator

permission_request 的 RememberScope 语义不准确

在发出 permission_request 事件时,RememberScope 被固定写成 always_session,但用户尚未做出 once/always/reject 选择。这会导致事件语义与真实状态不一致,可能误导 UI 和日志。建议请求事件留空或表达“可选项”,最终 scope 仅在 resolved 事件中写入真实值。

@pionxe

pionxe commented Apr 6, 2026

Copy link
Copy Markdown
Collaborator

Session 权限记忆粒度过粗会放大授权范围

sessionPermissionActionKey 只用 action type + category 作为键,不含目标(URL/路径)或命中规则。这样一次 allow_session 可能扩展到整类操作(如本会话所有 webfetch 目标),存在越权放大风险。若希望最小权限,建议把 host/path 归一化结果或 rule id 纳入 key

@minorcell minorcell merged commit 6891ac9 into 1024XEngineer:main Apr 6, 2026
2 checks passed
@Cai-Tang-www

Copy link
Copy Markdown
Collaborator Author

感谢详细 review,3 个点都已在本轮修复,commit:ca06d78。

ResolvePermission 重复提交阻塞

已在 runtime 增加幂等门禁(Submitted)并改为非阻塞提交,避免同一 request 被重复触发时卡在 channel 发送。
同时在 TUI 侧增加 pendingPermission.Submitted 状态,拦截 y/a/n 连续触发的重复提交。
相关文件:internal/runtime/permission.go、internal/tui/update.go、internal/tui/state.go
permission_request 的 RememberScope 语义

已移除 request 事件中的固定 always_session 赋值。
现在 RememberScope 仅在 permission_resolved 中携带用户最终选择,避免事件语义误导。
相关文件:internal/runtime/permission.go
Session 权限记忆粒度过粗

已将记忆 key 从 action type + category 收紧为 action type + category + target scope。
webfetch 按 host 维度归一;文件读取按目录 scope 归一,避免一次授权放大到整个类别。
相关文件:internal/tools/session_memory.go
另外已补充对应回归测试,并通过全量测试:go test ./...。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(security/runtime): 实现 session 级 once / always / reject 权限记忆P0-8

4 participants